﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using System.IO;
using System.Threading;

namespace DungDungShit
{
    class MenuScreen : Screen
    {
        public List<MenuEntry> menuEntries = new List<MenuEntry>();
        protected int selectedEntry = 0;
        private float prevYPos = 0.0f;
        private float YPos = 0.0f;
        private float nextYPos;
        private string menuTitle;
        private Viewport defaultViewport, menuEntryViewport;
        private float selectionChange = 1f;

        private int holdUpTime = 0;
        private int holdDownTime = 0;

        public MenuScreen(string menuTitle)
        {
            this.menuTitle = menuTitle;

            TransitionOnTime = TimeSpan.FromSeconds(0.3);
            TransitionOffTime = TimeSpan.FromSeconds(0.3);
        }

        public override void LoadContent()
        {
            defaultViewport = ScreenManager.GraphicsDevice.Viewport;

            menuEntryViewport = defaultViewport;
            menuEntryViewport.Y = ScreenManager.Font.LineSpacing * 4;
            menuEntryViewport.Height = ScreenManager.Font.LineSpacing * 9;
        }

        public override void HandleInput(InputState input)
        {
            if (input.IsMenuUp() || input.IsMenuUpHold() && holdUpTime > 10 && holdUpTime % 3 == 0)
            {
                prevYPos = (YPos + nextYPos) / 2;
                selectionChange = 0;
                do
                {
                    selectedEntry--;

                    if (selectedEntry < 0)
                        selectedEntry = menuEntries.Count - 1;
                } while (!menuEntries[selectedEntry].Enable);
            }

            if (input.IsMenuUpHold()) holdUpTime++;
            else holdUpTime = 0;

            // Move to the next menu entry?
            if (input.IsMenuDown() || input.IsMenuDownHold() && holdDownTime > 10 && holdDownTime % 3 == 0)
            {
                prevYPos = (YPos + nextYPos) / 2;
                selectionChange = 0;
                do
                {
                    selectedEntry++;

                    if (selectedEntry >= menuEntries.Count)
                        selectedEntry = 0;
                } while (!menuEntries[selectedEntry].Enable);
            }

            if (input.IsMenuDownHold()) holdDownTime++;
            else holdDownTime = 0;

            // 선택 할 때
            if (input.IsMenuSelect())
            {
                OnSelectEntry(selectedEntry);
            }
            // Cancel버튼 누를 때
            else if (input.IsMenuCancel())
            {
                OnCancel();
            }
        }

        protected virtual void OnSelectEntry(int entryIndex)
        {
            menuEntries[entryIndex].OnSelectEntry();
        }

        protected virtual void OnCancel()
        {
            
            ExitScreen();
        }

        protected virtual void OnCancel(object sender, EventArgs e)
        {
            OnCancel();
        }

        protected virtual void UpdateMenuEntryLocations()
        {
            // Make the menu slide into place during transitions, using a
            // power curve to make things look more interesting (this makes
            // the movement slow down as it nears the end).
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            // start at Y = 175; each X value is generated per entry
            // Y좌표를 계산한다. 개수가 적은 경우는 고정, 많은 경우는 스크롤한다.
            int count = menuEntries.Count;
            nextYPos = ScreenManager.Font.LineSpacing * 6 - selectedEntry * (ScreenManager.Font.LineSpacing - (menuEntryViewport.Height - ScreenManager.Font.LineSpacing * 4) / count) - menuEntryViewport.Y;
            if (count <= 7)
                YPos = 10 + menuEntryViewport.Y - count * ScreenManager.Font.LineSpacing / 2 + 90;
            else YPos = MathHelper.Lerp(prevYPos, nextYPos, selectionChange);

            float y = YPos;

            // update each menu entry's location in turn
            for (int i = 0; i < count; i++)
            {
                MenuEntry menuEntry = menuEntries[i];

                // each entry is to be centered horizontally
                float x = ScreenManager.GraphicsDevice.Viewport.Width / 2 + 200;// -menuEntry.GetWidth(this) / 2;

                if (ScreenState == ScreenState.TransitionOn)
                    x -= transitionOffset * 256;
                else
                    x += transitionOffset * 512;

                // set the entry's position
                menuEntry.Position = new Vector2(x, y);

                // move down for the next entry the size of this entry
                y += menuEntry.GetHeight(this);
            }
        }


        /// <summary>
        /// Updates the menu.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            // Update each nested MenuEntry object.
            for (int i = 0; i < menuEntries.Count; i++)
            {
                bool isSelected = IsActive && (i == selectedEntry);

                menuEntries[i].Update(this, isSelected, gameTime);
            }

            float changeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;

            selectionChange = Math.Min(selectionChange + changeSpeed, 1f);
        }

        public override void Draw(GameTime gameTime)
        {
            // make sure our entries are in the right place before we draw them
            UpdateMenuEntryLocations();

            SpriteFont font = ScreenManager.Font;

            ScreenManager.GraphicsDevice.Viewport = menuEntryViewport;
            ScreenManager.SpriteBatch.Begin();

            // Draw each menu entry in turn.
            for (int i = 0; i < menuEntries.Count; i++)
            {
                MenuEntry menuEntry = menuEntries[i];

                bool isSelected = IsActive && (i == selectedEntry);

                menuEntry.Draw(this, isSelected, gameTime);
            }
            ScreenManager.SpriteBatch.End();

            ScreenManager.GraphicsDevice.Viewport = defaultViewport;
            ScreenManager.SpriteBatch.Begin();
            // Make the menu slide into place during transitions, using a
            // power curve to make things look more interesting (this makes
            // the movement slow down as it nears the end).
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            // Draw the menu title centered on the screen
            Vector2 titlePosition = new Vector2(defaultViewport.Width / 2, 90 + 200);
            Vector2 titleOrigin = font.MeasureString(menuTitle) / 2;
            Color titleColor = new Color(32, 216, 32) * TransitionAlpha;
            float titleScale = 1f;

            titlePosition.Y -= transitionOffset * 100;

            ScreenManager.SpriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0,
                                   titleOrigin, titleScale, SpriteEffects.None, 0);

            ScreenManager.SpriteBatch.End();
        }
    }
}
